home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 4
/
Meeting Pearls Vol. IV (1996)(GTI - Schatztruhe)[!].iso
/
Pearls
/
dev
/
Oberon
/
OberonV4
/
system
/
TableElems.Mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1994-07-28
|
22KB
|
512 lines
Syntax10.Scn.Fnt
Syntax10i.Scn.Fnt
Syntax10b.Scn.Fnt
Syntax12.Scn.Fnt
MODULE TableElems; (** CAS 13-May-92 / 28-Sep-93 **)
IMPORT
Input, Display, Fonts, Printer, Files, Oberon, Texts, TextFrames, Viewers, MenuViewers, TextPrinter;
CONST
Menu = "System.Close Edit.Search Edit.Replace All Edit.Parcs TableElems.Update ";
mm = TextFrames.mm; Scale = mm DIV 10; MinW = 3*mm; MinH = 3*mm;
unit = TextFrames.Unit; Unit = TextPrinter.Unit;
middleKey = 1;
TAB = 9X; CR = 0DX;
MaxCol = 32; MaxRow = 32;
(*elem.opts set elements*)
headCol = 0; headRow = 1; colL = 2; rowL = 3; leftL = 4; rightL = 5; topL = 6; botL = 7;
TYPE
Row = POINTER TO RowDesc;
RowDesc = RECORD
next: Row;
lsp, dsr: LONGINT;
pos: ARRAY MaxCol OF LONGINT;
x, y: ARRAY MaxCol OF LONGINT
END;
Elem* = POINTER TO ElemDesc;
ElemDesc* = RECORD(Texts.ElemDesc)
def*: Texts.Text;
parc: TextFrames.Parc;
opts: SET;
nofCols, nofRows: INTEGER;
lw: LONGINT;
width: ARRAY MaxCol OF LONGINT;
row: Row (*rows chained from bottom to top*)
END;
Viewer* = POINTER TO ViewerDesc;
ViewerDesc* = RECORD(MenuViewers.ViewerDesc)
elem*: Elem
END;
W: Texts.Writer;
PROCEDURE Min (x, y: LONGINT): LONGINT;
BEGIN
IF x < y THEN RETURN x ELSE RETURN y END
END Min;
PROCEDURE Max (x, y: LONGINT): LONGINT;
BEGIN
IF x > y THEN RETURN x ELSE RETURN y END
END Max;
PROCEDURE UnmarkMenu (V: Viewers.Viewer);
VAR R: Texts.Reader; T: Texts.Text; ch: CHAR;
BEGIN T := V.dsc(TextFrames.Frame).text;
Texts.OpenReader(R, T, T.len - 1); Texts.Read(R, ch);
IF ch = "!" THEN Texts.Delete(T, T.len - 1, T.len) END
END UnmarkMenu;
(* generate table structure *)
PROCEDURE Matches (VAR S: Texts.Scanner; key: ARRAY OF CHAR): BOOLEAN;
VAR i: INTEGER;
BEGIN i := 0;
WHILE (S.s[i] # 0X) & (CAP(S.s[i]) = key[i]) DO INC(i) END;
RETURN (S.class = Texts.Name) & ((key[i] = 0X) OR (i >= 3)) & (S.s[i] = 0X)
END Matches;
PROCEDURE Opts (s: ARRAY OF CHAR): SET;
VAR opts: SET; i: INTEGER; ch: CHAR;
BEGIN opts := {}; i := 0;
WHILE s[i] # 0X DO ch := CAP(s[i]);
IF ch = "H" THEN INCL(opts, headRow)
ELSIF ch = "V" THEN INCL(opts, headCol)
ELSIF s[i] = "*" THEN opts := {headRow, headCol}
END;
INC(i)
END;
RETURN opts
END Opts;
PROCEDURE LineOpts (s: ARRAY OF CHAR): SET;
VAR opts: SET; i: INTEGER; ch: CHAR;
BEGIN opts := {}; i := 0;
WHILE s[i] # 0X DO ch := CAP(s[i]);
IF ch = "H" THEN INCL(opts, rowL)
ELSIF ch = "V" THEN INCL(opts, colL)
ELSIF ch = "L" THEN INCL(opts, leftL)
ELSIF ch = "R" THEN INCL(opts, rightL)
ELSIF ch = "T" THEN INCL(opts, topL)
ELSIF ch = "B" THEN INCL(opts, botL)
ELSIF s[i] = "*" THEN opts := {rowL, colL, leftL, rightL, topL, botL}
END;
INC(i)
END;
RETURN opts
END LineOpts;
PROCEDURE ColOpts (VAR cm: ARRAY OF CHAR; s: ARRAY OF CHAR);
VAR i: INTEGER; ch: CHAR;
BEGIN i := 0;
WHILE (s[i] # 0X) & (i < LEN(cm)) DO ch := CAP(s[i]);
IF (ch = "C") OR (ch = "L") OR (ch = "N") OR (ch = "R") THEN cm[i] := ch END;
INC(i)
END
END ColOpts;
PROCEDURE RowOpts (VAR rm: ARRAY OF CHAR; s: ARRAY OF CHAR);
VAR i: INTEGER; ch: CHAR;
BEGIN i := 0;
WHILE (s[i] # 0X) & (i < LEN(rm)) DO ch := CAP(s[i]);
IF (ch = "B") OR (ch = "C") OR (ch = "L") OR (ch = "T") THEN rm[i] := ch END;
INC(i)
END
END RowOpts;
PROCEDURE Offset (VAR R: Texts.Reader): LONGINT;
BEGIN
IF R.voff = 0 THEN RETURN 0 ELSE RETURN LONG(R.fnt.height) * unit * R.voff DIV 64 END
END Offset;
PROCEDURE DispPrepElem (E: Elem; e: Texts.Elem; fnt: Fonts.Font; col: SHORTINT; pos: LONGINT);
VAR disp: TextFrames.DisplayMsg;
BEGIN disp.prepare := TRUE;
disp.fnt := fnt; disp.col := col; disp.pos := pos; disp.indent := 0; e.handle(e, disp)
END DispPrepElem;
PROCEDURE PrintPrepElem (E: Elem; e: Texts.Elem; fnt: Fonts.Font; col: SHORTINT; pno: INTEGER; pos: LONGINT);
VAR print: TextPrinter.PrintMsg;
BEGIN print.prepare := TRUE;
print.fnt := fnt; print.col := col; print.pos := pos; print.indent := 0; print.pno := pno; e.handle(e, print)
END PrintPrepElem;
PROCEDURE GetElem (E: Elem; e: Texts.Elem;
fnt: Fonts.Font; col: SHORTINT; pos: LONGINT; VAR dx, x, y, w, h: LONGINT);
BEGIN x := 0; y := -E.parc.dsr;
DispPrepElem(E, e, fnt, col, pos); dx := e.W; h := e.H;
PrintPrepElem(E, e, fnt, col, -1, pos); dx := Max(dx, e.W); h := Max(h, e.H); w := dx
END GetElem;
PROCEDURE Parse (E: Elem): LONGINT;
CONST StrClass = {Texts.Name, Texts.String};
VAR S: Texts.Scanner; row: Row; pbeg, beg, pos: LONGINT; state, st, r, c: INTEGER; ch, period: CHAR;
margL, margR, margB, margT, gridW, lsp, dsr, min, max, cmin, cmax, cw, wl, wr, dx, x, y, w, h: LONGINT;
cm: ARRAY MaxCol OF CHAR;
rm: ARRAY MaxRow OF CHAR;
h1, h2, w1, w2: ARRAY MaxRow, MaxCol OF LONGINT;
PROCEDURE Setup;
BEGIN E.opts := {headRow, headCol, colL, rowL, leftL, rightL, topL, botL}; E.lw := 2*Scale; period := ".";
r := 0; WHILE r < MaxRow DO rm[r] := "L"; INC(r) END;
cm[0] := "L"; c := 1; WHILE c < MaxCol DO cm[c] := "N"; INC(c) END;
margL := 1*mm; margR := margL; margB := 3*Scale; margT := margB; gridW := 5*mm
END Setup;
PROCEDURE Scan (VAR S: Texts.Scanner);
VAR i: SHORTINT; ch: CHAR;
BEGIN ch := S.nextCh; i := 0;
LOOP
IF ch = CR THEN INC(S.line)
ELSIF (ch # " ") & (ch # TAB) THEN EXIT
END;
Texts.Read(S, ch)
END;
IF ("A" <= CAP(ch)) & (CAP(ch) <= "Z") THEN
REPEAT S.s[i] := ch; INC(i); Texts.Read(S, ch)
UNTIL (CAP(ch) > "Z")
OR ("A" > CAP(ch)) & (ch > "9")
OR ("0" > ch) & (ch # ".")
OR (i = LEN(S.s)-1);
S.s[i] := 0X; S.len := i; S.class := Texts.Name; S.nextCh := ch
ELSIF ch = "/" THEN S.class := 6; S.c := ch; Texts.Read(S, S.nextCh)
ELSE S.nextCh := ch; Texts.Scan(S)
END
END Scan;
PROCEDURE Options;
BEGIN Texts.OpenScanner(S, E.def, 0); Scan(S);
LOOP
IF S.eot THEN RETURN
ELSIF (S.class = Texts.Char) & (S.c = "/") THEN Scan(S);
IF Matches(S, "TABLE") THEN RETURN
ELSIF Matches(S, "BOTTOM") THEN Scan(S);
IF (S.class = Texts.Int) & (0 <= S.i) & (S.i <= 100) THEN margB := S.i*Scale END
ELSIF Matches(S, "COLUMNS") THEN Scan(S);
IF S.class IN StrClass THEN ColOpts(cm, S.s) END
ELSIF Matches(S, "GRID") THEN Scan(S);
IF (S.class = Texts.Int) & (0 <= S.i) & (S.i <= 100) THEN gridW := S.i*Scale END
ELSIF Matches(S, "HEADS") THEN Scan(S);
IF S.class IN StrClass THEN E.opts := E.opts + Opts(S.s) END
ELSIF Matches(S, "LEFT") THEN Scan(S);
IF (S.class = Texts.Int) & (0 <= S.i) & (S.i <= 100) THEN margL := S.i*Scale END
ELSIF Matches(S, "LINES") THEN Scan(S);
IF S.class IN StrClass THEN E.opts := E.opts + LineOpts(S.s) END
ELSIF Matches(S, "NOHEADS") THEN Scan(S);
IF S.class IN StrClass THEN E.opts := E.opts - Opts(S.s) END
ELSIF Matches(S, "NOLINES") THEN Scan(S);
IF S.class IN StrClass THEN E.opts := E.opts - LineOpts(S.s) END
ELSIF Matches(S, "PERIOD") THEN Scan(S);
IF S.class IN StrClass THEN period := S.s[0] END
ELSIF Matches(S, "RIGHT") THEN Scan(S);
IF (S.class = Texts.Int) & (0 <= S.i) & (S.i <= 100) THEN margR := S.i*Scale END
ELSIF Matches(S, "ROWS") THEN Scan(S);
IF S.class IN StrClass THEN RowOpts(rm, S.s) END
ELSIF Matches(S, "TOP") THEN Scan(S);
IF (S.class = Texts.Int) & (0 <= S.i) & (S.i <= 100) THEN margT := S.i*Scale END
ELSIF Matches(S, "WIDTHS") THEN Scan(S);
IF (S.class = Texts.Int) & (1 <= S.i) & (S.i <= 10) THEN E.lw := S.i*Scale END
END;
Scan(S)
ELSE Scan(S)
END
END
END Options;
PROCEDURE AcceptCell;
BEGIN row.pos[c] := pos; w1[r, c] := cw; h1[r, c] := cmax - cmin; h2[r, c] := -cmin;
min := Min(min, cmin); max := Max(max, cmax);
CASE state OF
0, 1: w2[r, c] := cw
| 2: w2[r, c] := wl
| 3: w2[r, c] := -1
END;
pos := Texts.Pos(S); INC(c); cmin := -E.parc.dsr; cmax := 0; cw := 0; state := 0;
IF c > E.nofCols THEN
IF c < MaxCol THEN INC(E.nofCols) ELSE DEC(c) END
END
END AcceptCell;
BEGIN Setup; Options; INC(margL, E.lw); INC(margR, E.lw); INC(margB, E.lw); INC(margT, E.lw);
E.nofCols := 0; E.nofRows := 0;
ch := S.nextCh; WHILE ~S.eot & (ch # CR) DO Texts.Read(S, ch) END;
beg := Texts.Pos(S); TextFrames.ParcBefore(E.def, beg, E.parc, pbeg);
(*parse*)
pos := beg; E.row := NIL;
IF ~S.eot THEN NEW(row); r := 0; min := 0; max := 0; c := 0; cmin := -E.parc.dsr; cmax := 0; cw := 0; state := 0;
LOOP Texts.Read(S, ch);
IF S.eot THEN EXIT
ELSIF ch = CR THEN AcceptCell;
IF TextFrames.gridAdj IN E.parc.opts THEN dsr := E.parc.dsr;
WHILE dsr < -min DO INC(dsr, E.parc.lsp) END;
lsp := Max(E.parc.lsp, dsr + max); INC(lsp, (-lsp) MOD E.parc.lsp)
ELSE dsr := Max(E.parc.dsr, -min); lsp := Max(E.parc.lsp, dsr + max)
END;
row.dsr := dsr + margB; row.lsp := lsp + margB + margT;
WHILE c < MaxCol DO
row.pos[c] := E.def.len; h1[r, c] := 0; h2[r, c] := 0; w1[r, c] := 0; w2[r, c] := -1; INC(c)
END;
row.next := E.row; E.row := row; INC(r); IF r = MaxRow THEN EXIT END;
NEW(row); min := 0; max := 0; c := 0
ELSIF ch = TAB THEN AcceptCell
ELSE st := state;
IF (state < 2) & (ch = period) THEN wl := cw; state := 2
ELSIF (state = 0) & ((ch >= "0") & (ch <= "9") OR (ch = "+") OR (ch = "-") OR (ch = "#")) THEN state := 1
ELSIF state = 0 THEN state := 3
END;
IF (st # 0) OR (ch # "#") & (ch # "&") THEN
IF (S.elem # NIL) & ~(S.elem IS TextFrames.Parc) THEN
GetElem(E, S.elem, S.fnt, S.col, Texts.Pos(S)-1, dx, x, y, w, h)
ELSE TextPrinter.Get(TextPrinter.FontNo(S.fnt), ch, dx, x, y, w, h)
END;
INC(y, Offset(S)); cmin := Min(cmin, y); cmax := Max(cmax, y + h); INC(cw, dx)
END
END
END;
E.nofRows := r
END;
(*format*)
IF E.nofRows < 2 THEN EXCL(E.opts, headRow) END;
IF E.nofCols < 2 THEN EXCL(E.opts, headCol) END;
c := 0;
WHILE c < E.nofCols DO
IF cm[c] = "N" THEN wl := 0; wr := 0; r := 0;
WHILE r < E.nofRows DO
IF w2[r, c] > wl THEN wl := w2[r, c] END;
IF (w2[r, c] >= 0) & (w1[r, c] - w2[r, c] > wr) THEN wr := w1[r, c] - w2[r, c] END;
INC(r)
END;
cw := wl + wr
ELSE cw := 0
END;
r := 0;
WHILE r < E.nofRows DO
IF w1[r, c] > cw THEN cw := w1[r, c] END;
INC(r)
END;
INC(cw, margL + margR);
IF gridW > 0 THEN INC(cw, (-cw) MOD gridW) END;
r := E.nofRows; row := E.row;
WHILE r > 0 DO DEC(r);
IF cm[c] = "L" THEN row.x[c] := margL
ELSIF cm[c] = "R" THEN row.x[c] := cw - margR - w1[r, c]
ELSIF (cm[c] = "C") OR (w2[r, c] = -1) THEN row.x[c] := (cw - w1[r, c]) DIV 2
ELSIF cm[c] = "N" THEN row.x[c] := (cw - wl - wr) DIV 2 + wl - w2[r, c]
END;
IF rm[r] = "B" THEN row.y[c] := margB + h2[r, c]
ELSIF rm[r] = "T" THEN row.y[c] := row.lsp - h1[r, c] - margB + h2[r, c]
ELSIF rm[r] = "C" THEN row.y[c] := (row.lsp - h1[r, c]) DIV 2 + h2[r, c]
ELSIF rm[r] = "L" THEN row.y[c] := row.dsr
END;
row := row.next
END;
E.width[c] := cw;
INC(c)
END;
RETURN beg
END Parse;
(* operations on elements *)
PROCEDURE CopyText* (T: Texts.Text): Texts.Text;
VAR B: Texts.Buffer; t: Texts.Text;
BEGIN NEW(B); Texts.OpenBuf(B); Texts.Save(T, 0, T.len, B);
NEW(t); Texts.Open(t, ""); t.notify := T.notify;
Texts.Append(t, B); RETURN t
END CopyText;
PROCEDURE Open* (E: Elem; def: Texts.Text);
VAR row: Row; beg: LONGINT; i: INTEGER;
BEGIN
E.def := def; beg := Parse(E);
E.W := 0; i := 0; WHILE i < E.nofCols DO INC(E.W, E.width[i]); INC(i) END;
E.H := 0; row := E.row; WHILE row # NIL DO INC(E.H, row.lsp); row := row.next END;
IF (headRow IN E.opts) & (rowL IN E.opts) THEN INC(E.H, E.lw * 2) END;
IF (headCol IN E.opts) & (colL IN E.opts) THEN INC(E.W, E.lw * 2) END;
IF E.W < MinW THEN E.W := MinW END;
IF E.H < MinH THEN E.H := MinH END
END Open;
PROCEDURE Load* (E: Elem; VAR r: Files.Rider);
VAR text: Texts.Text; f: Files.File; pos, len: LONGINT; version, tag: CHAR;
BEGIN Files.Read(r, version); NEW(text); Texts.Load(r, text); text.notify := TextFrames.NotifyDisplay;
Open(E, text)
END Load;
PROCEDURE Store* (E: Elem; VAR r: Files.Rider);
VAR f: Files.File; pos, len: LONGINT;
BEGIN Files.Write(r, 1X); Texts.Store(r, E.def)
END Store;
PROCEDURE Changed* (E: Elem);
VAR R: Texts.Reader; T: Texts.Text;
BEGIN T := Texts.ElemBase(E);
IF T # NIL THEN Texts.OpenReader(R, T, 0);
REPEAT Texts.ReadElem(R) UNTIL R.elem = E;
T.notify(T, Texts.replace, Texts.Pos(R)-1, Texts.Pos(R))
END
END Changed;
PROCEDURE Line (x, y, w, h: INTEGER);
BEGIN Display.ReplConst(Display.white, x, y, w, h, Display.replace)
END Line;
PROCEDURE DrawString (E: Elem; F: Display.Frame; pos: LONGINT; x0, y0: INTEGER);
VAR R: Texts.Reader; e: Texts.Elem; pat: Display.Pattern;
px, pdx: LONGINT; dx, x, y, w, h: INTEGER; ch: CHAR;
disp: TextFrames.DisplayMsg;
BEGIN Texts.OpenReader(R, E.def, pos); Texts.Read(R, ch); px := LONG(x0) * unit;
IF (ch = "#") OR (ch = "&") THEN Texts.Read(R, ch) END;
WHILE ~R.eot & (ch # TAB) & (ch # CR) DO
IF R.elem # NIL THEN
IF R.elem IS TextFrames.Parc THEN pdx := 0
ELSE e := R.elem;
DispPrepElem(E, e, R.fnt, R.col, Texts.Pos(R)-1); pdx := e.W;
disp.prepare := FALSE; disp.fnt := R.fnt; disp.col := R.col; disp.pos := Texts.Pos(R)-1; disp.frame := F;
disp.X0 := SHORT(px DIV unit); disp.Y0 := y0 + SHORT((Offset(R) - E.parc.dsr) DIV unit);
disp.indent := 0;
e.handle(e, disp)
END
ELSE TextPrinter.GetChar(TextPrinter.FontNo(R.fnt), unit, ch, pdx, dx, x, y, w, h, pat);
Display.CopyPattern(R.col, pat,
SHORT(px DIV unit) + x, y0 + SHORT(Offset(R) DIV unit) + y, Display.replace)
END;
INC(px, pdx); Texts.Read(R, ch)
END
END DrawString;
PROCEDURE Draw* (E: Elem; F: Display.Frame; x0, y0: INTEGER);
VAR row: Row; r, c, x, y, w, h, h1, lw, d: INTEGER;
PROCEDURE Align(x: LONGINT): LONGINT;
BEGIN RETURN x + (-x) MOD unit
END Align;
BEGIN
IF (E.nofRows = 0) OR (E.nofCols = 0) THEN w := SHORT(E.W DIV unit); h := SHORT(E.H DIV unit);
Display.ReplPattern(Display.white, Display.grey1, x0, y0, w, h, Display.replace)
ELSE r := E.nofRows; row := E.row;
y := y0; lw := SHORT(Align(E.lw) DIV unit); d := SHORT(E.lw * 2 DIV unit);
WHILE r > 0 DO DEC(r); x := x0; c := 0; h := SHORT(row.lsp DIV unit); h1 := h;
IF (r = 1) & (headRow IN E.opts) & (rowL IN E.opts) THEN INC(h1, d) END;
WHILE c < E.nofCols DO w := SHORT(E.width[c] DIV unit);
IF c = 0 THEN
IF headCol IN E.opts THEN Line(x + w - lw, y, lw, h);
IF colL IN E.opts THEN INC(w, d) END
END;
IF leftL IN E.opts THEN Line(x, y, lw, h1) END
ELSIF colL IN E.opts THEN Line(x, y, lw, h)
END;
IF (c = E.nofCols - 1) & (rightL IN E.opts) THEN Line(x + w - lw, y, lw, h1) END;
IF (r = 0) & (topL IN E.opts) OR (r = 1) & (headRow IN E.opts) THEN
Line(x, y + h - lw, w, lw)
END;
IF (r = E.nofRows - 1) & (botL IN E.opts) OR (r < E.nofRows - 1) & (rowL IN E.opts) THEN
Line(x, y, w, lw)
END;
DrawString(E, F, row.pos[c], x + SHORT(row.x[c] DIV unit), y + SHORT(row.y[c] DIV unit));
INC(x, w); INC(c)
END;
INC(y, h1); row := row.next
END
END
END Draw;
PROCEDURE PrintString (E: Elem; pos: LONGINT; pno, x0, y0: INTEGER);
VAR R: Texts.Reader; e: Texts.Elem; fnt: Fonts.Font;
i, w, dy: INTEGER; voff, fno: SHORTINT; ch: CHAR; first: BOOLEAN;
print: TextPrinter.PrintMsg; s: ARRAY 256 OF CHAR;
BEGIN Texts.OpenReader(R, E.def, pos); Texts.Read(R, ch); first := TRUE;
IF (ch = "#") OR (ch = "&") THEN Texts.Read(R, ch) END;
WHILE ~R.eot & (ch # TAB) & (ch # CR) DO
WHILE ~R.eot & (R.elem # NIL) DO
IF ~(R.elem IS TextFrames.Parc) THEN e := R.elem;
PrintPrepElem(E, e, R.fnt, R.col, pno, Texts.Pos(R)-1);
print.prepare := FALSE; print.indent := 0; print.fnt := R.fnt; print.col := R.col; print.pos := Texts.Pos(R)-1;
print.X0 := x0; print.Y0 := y0 + SHORT((Offset(R) - E.parc.dsr) DIV Unit); print.pno := pno;
e.handle(e, print); INC(x0, SHORT(e.W DIV Unit)); first := TRUE
END;
Texts.Read(R, ch)
END;
IF ~R.eot & (ch # TAB) & (ch # CR) THEN
fnt := R.fnt; fno := TextPrinter.FontNo(fnt); voff := R.voff;
dy := SHORT(Offset(R) DIV Unit); i := 0; w := 0;
REPEAT s[i] := ch; INC(i); INC(w, SHORT(TextPrinter.DX(fno, ch) DIV Unit)); Texts.Read(R, ch)
UNTIL R.eot OR (R.elem # NIL) OR (ch = TAB) OR (ch = CR)
OR (fno # TextPrinter.FontNo(R.fnt)) OR (voff # R.voff) OR (i = LEN(s)-1);
s[i] := 0X;
IF voff # 0 THEN Printer.String(x0, y0 + dy, s, fnt.name); first := TRUE
ELSIF first THEN Printer.String(x0, y0 + dy, s, fnt.name); first := FALSE
ELSE Printer.ContString(s, fnt.name)
END;
INC(x0, w)
END
END
END PrintString;
PROCEDURE Print* (E: Elem; pno, x0, y0: INTEGER);
VAR row: Row; r, c, x, y, w, h, h1, lw, d: INTEGER;
BEGIN r := E.nofRows; row := E.row; y := y0; lw := SHORT(E.lw DIV Unit); d := SHORT(E.lw * 2 DIV Unit);
WHILE r > 0 DO DEC(r); x := x0; c := 0; h := SHORT(row.lsp DIV Unit); h1 := h;
IF (r = 1) & (headRow IN E.opts) & (rowL IN E.opts) THEN INC(h1, d) END;
WHILE c < E.nofCols DO w := SHORT(E.width[c] DIV Unit);
IF c = 0 THEN
IF headCol IN E.opts THEN Printer.ReplConst(x + w - lw, y, lw, h);
IF colL IN E.opts THEN INC(w, d) END
END;
IF leftL IN E.opts THEN Printer.ReplConst(x, y, lw, h1) END
ELSIF colL IN E.opts THEN Printer.ReplConst(x, y, lw, h)
END;
IF (c = E.nofCols - 1) & (rightL IN E.opts) THEN Printer.ReplConst(x + w - lw, y, lw, h1) END;
IF (r = 0) & (topL IN E.opts) OR (r = 1) & (headRow IN E.opts) THEN
Printer.ReplConst(x, y + h - lw, w, lw)
END;
IF (r = E.nofRows - 1) & (botL IN E.opts) OR (r < E.nofRows - 1) & (rowL IN E.opts) THEN
Printer.ReplConst(x, y, w, lw)
END;
PrintString(E, row.pos[c], pno, x + SHORT(row.x[c] DIV Unit), y + SHORT(row.y[c] DIV Unit));
INC(x, w); INC(c)
END;
INC(y, h1); row := row.next
END
END Print;
PROCEDURE OpenViewer* (E: Elem);
VAR V: Viewer; menu: TextFrames.Frame; body: TextFrames.Frame; x, y: INTEGER;
restore: Viewers.ViewerMsg;
BEGIN Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
menu := TextFrames.NewMenu("TableElems.Text", Menu);
body := TextFrames.NewText(CopyText(E.def), 0);
NEW(V); V.handle := MenuViewers.Handle; V.dsc := menu; V.dsc.next := body;
V.menuH := TextFrames.menuH; V.elem := E;
Viewers.Open(V, x, y); restore.id := Viewers.restore; V.handle(V, restore)
END OpenViewer;
PROCEDURE Track* (E: Elem; pos: LONGINT; keys: SET; x, y, x0, y0: INTEGER);
VAR keysum: SET;
BEGIN
IF middleKey IN keys THEN keysum := keys;
REPEAT Input.Mouse(keys, x, y); Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y);
keysum := keysum + keys
UNTIL keys = {};
IF keysum = {middleKey} THEN OpenViewer(E) END
END
END Track;
(* handle elements *)
PROCEDURE Handle* (E: Texts.Elem; VAR msg: Texts.ElemMsg);
VAR e: Elem;
BEGIN
WITH E: Elem DO
WITH
msg: TextFrames.DisplayMsg DO
IF ~msg.prepare THEN Draw(E, msg.frame, msg.X0, msg.Y0) END
| msg: TextPrinter.PrintMsg DO
IF ~msg.prepare THEN Print(E, msg.pno, msg.X0, msg.Y0) END
| msg: Texts.IdentifyMsg DO
msg.mod := "TableElems"; msg.proc := "Alloc"
| msg: Texts.FileMsg DO
IF msg.id = Texts.load THEN Load(E, msg.r)
ELSIF msg.id = Texts.store THEN Store(E, msg.r)
END
| msg: Texts.CopyMsg DO
NEW(e); Texts.CopyElem(E, e); Open(e, CopyText(E.def)); msg(Texts.CopyMsg).e := e
| msg: TextFrames.TrackMsg DO
Track(E, msg.pos, msg.keys, msg.X, msg.Y, msg.X0, msg.Y0)
ELSE (*ignore*)
END
END
END Handle;
PROCEDURE Alloc*;
VAR e: Elem;
BEGIN NEW(e); e.handle := Handle; Texts.new := e
END Alloc;
(* commands *)
PROCEDURE Insert*; (** ["^" | name] **)
VAR S: Texts.Scanner; text: Texts.Text; beg, end, time: LONGINT;
e: Elem; t: Texts.Text; m: TextFrames.InsertElemMsg;
BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S);
IF (S.class = Texts.Char) & (S.c = "^") THEN
Oberon.GetSelection(text, beg, end, time);
IF time >= 0 THEN Texts.OpenScanner(S, text, beg); Texts.Scan(S) END
END;
IF (S.class = Texts.Name) & (S.line = 0) THEN t := TextFrames.Text(S.s)
ELSE t := TextFrames.Text("");
Texts.WriteString(W, "/table"); Texts.WriteLn(W);
Texts.Append(t, W.buf)
END;
NEW(e); e.handle := Handle; Open(e, t); m.e := e;
Oberon.FocusViewer.handle(Oberon.FocusViewer, m)
END Insert;
PROCEDURE Update*;
VAR V: Viewer; F: TextFrames.Frame;
BEGIN V := Oberon.Par.vwr(Viewer); F := V.dsc.next(TextFrames.Frame);
Open(V.elem, CopyText(F.text)); Changed(V.elem); UnmarkMenu(V)
END Update;
BEGIN Texts.OpenWriter(W)
END TableElems.
Edit.Open ^ test.Txt TableElems.Insert ^ testTable.Txt System.Free TableElems ~